package com.avic.modules.record.service.impl;

import com.avic.common.service.impl.BaseServiceImpl;
import com.avic.common.utils.QueryHelpPlus;
import com.avic.dozer.service.IGenerator;
import com.avic.exception.BadRequestException;
import com.avic.modules.equipment.cache.CacheService;
import com.avic.modules.equipment.constants.EquipConstant;
import com.avic.modules.equipment.domain.Equipment;
import com.avic.modules.equipment.service.EquipmentOperationService;
import com.avic.modules.equipment.service.EquipmentService;
import com.avic.modules.equipment.service.dto.EquipmentQueryCriteria;
import com.avic.modules.equipment.service.mapper.EquipmentMapper;
import com.avic.modules.mapping.domain.DataMapping;
import com.avic.modules.mapping.domain.vo.DataMappingVo;
import com.avic.modules.mapping.service.mapper.DataMappingMapper;
import com.avic.modules.realtime.constants.RedisOPCItem;
import com.avic.modules.record.domain.AlarmInformation;
import com.avic.enums.AlarmEnum;
import com.avic.modules.record.service.AlarmInformationService;
import com.avic.modules.record.service.dto.AlarmInformationDto;
import com.avic.modules.record.service.dto.AlarmInformationQueryCriteria;
import com.avic.modules.record.service.mapper.AlarmInformationMapper;
import com.avic.modules.statistics.domain.KanbanStatistics;
import com.avic.modules.statistics.domain.MonthlyStatistics;
import com.avic.modules.statistics.domain.MonthlyStatusRecord;
import com.avic.modules.statistics.service.KanbanStatisticsService;
import com.avic.modules.statistics.service.MonthlyStatisticsService;
import com.avic.modules.statistics.service.MonthlyStatusRecordService;
import com.avic.modules.system.domain.DictDetail;
import com.avic.modules.system.domain.User;
import com.avic.modules.system.service.mapper.DictDetailMapper;
import com.avic.modules.system.service.mapper.SysUserMapper;
import com.avic.utils.RedisUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhangzikang 报警/工作记录表
 * @date 2022-08-14
 */
@Service(value = "alarmInformationService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AlarmInformationServiceImpl extends BaseServiceImpl
        <AlarmInformationMapper, AlarmInformation> implements AlarmInformationService {

    // 类型
    private final Long type = 2L;
    // 子设备
    private final int auxiliary = 2;

    private final AlarmInformationMapper alarmInformationMapper;
    private final DataMappingMapper dataMappingMapper;
    private final EquipmentService equipmentService;
    private final KanbanStatisticsService kanbanStatisticsService;
    private final RedisUtils redisUtils;
    private final SysUserMapper sysUserMapper;
    private final EquipmentMapper equipmentMapper;
    private final EquipmentOperationService equipmentOperationService;
    private final IGenerator generator;
    private final DictDetailMapper dictDetailMapper;
    private final CacheService cacheService;
    private final MonthlyStatusRecordService monthlyStatusRecordService;
    private final MonthlyStatisticsService monthlyStatisticsService;

    public AlarmInformationServiceImpl(AlarmInformationMapper alarmInformationMapper, DataMappingMapper dataMappingMapper, EquipmentService equipmentService, KanbanStatisticsService kanbanStatisticsService, RedisUtils redisUtils, SysUserMapper sysUserMapper, EquipmentMapper equipmentMapper, EquipmentOperationService equipmentOperationService, IGenerator generator, DictDetailMapper dictDetailMapper, CacheService cacheService, MonthlyStatusRecordService monthlyStatusRecordService, MonthlyStatisticsService monthlyStatisticsService) {
        this.alarmInformationMapper = alarmInformationMapper;
        this.dataMappingMapper = dataMappingMapper;
        this.equipmentService = equipmentService;
        this.kanbanStatisticsService = kanbanStatisticsService;
        this.redisUtils = redisUtils;
        this.sysUserMapper = sysUserMapper;
        this.equipmentMapper = equipmentMapper;
        this.equipmentOperationService = equipmentOperationService;
        this.generator = generator;
        this.dictDetailMapper = dictDetailMapper;
        this.cacheService = cacheService;
        this.monthlyStatusRecordService = monthlyStatusRecordService;
        this.monthlyStatisticsService = monthlyStatisticsService;
        this.queryDataMapping();
    }

    /**
     * 查看报警记录
     *
     * @param pageable 分页数据
     * @return
     */
    @Override
    public Map<String, Object> callThePolice(Pageable pageable) {
        QueryWrapper<AlarmInformation> wrapper = new QueryWrapper<>();
        List<Integer> objects = new ArrayList<>();
        objects.add(0);// 任务报警
        objects.add(2);// 报警
        wrapper.in("type", objects);
        wrapper.orderByDesc("create_time");
        String order = "create_time desc";
        getPageSort(pageable, order);
        PageInfo<AlarmInformation> page = new PageInfo<>(this.list(wrapper));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", page.getList());
        map.put("totalElements", page.getTotal());
        return map;
    }

    /**
     * 查看设备全部信息 分页
     *
     * @param criteria
     * @return
     */
    @Override
    public Map<String, Object> queryAll(AlarmInformationQueryCriteria criteria, Pageable pageable) {
        if (criteria.getStation() != null && !criteria.getStation().equals("")) {
            QueryWrapper<Equipment> wrapper = new QueryWrapper<>();
            wrapper.eq("stack_number", criteria.getStation());
            wrapper.eq("equip_category_id", criteria.getCategory());
            wrapper.eq("device_type", EquipConstant.SUB_DEVICE_TYPE);// 辅助设备
            List<Equipment> equipment = equipmentMapper.selectList(wrapper);
            Set<String> equipAll = new HashSet<>();
            for (Equipment equip : equipment) {
                equipAll.add(equip.getId());
            }
            criteria.setEquipAll(equipAll);
        }
        String order = "create_time desc";
        getPageSort(pageable, order);
        PageInfo<AlarmInformation> page = new PageInfo<>(queryAll(criteria));
        List<AlarmInformationDto> convert = generator.convert(page.getList(), AlarmInformationDto.class);
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", convert);
        map.put("totalElements", page.getTotal());
        return map;
    }

    /**
     * 查看设备全部信息 不分页
     *
     * @param criteria
     * @return
     */
    public List<AlarmInformation> queryAll(AlarmInformationQueryCriteria criteria) {
        return baseMapper.selectList(QueryHelpPlus.getPredicate(AlarmInformation.class, criteria));
    }

    /**
     * 添加报警记录
     */
    @Override
    public void addAlarmInformation(List<DataMapping> list, String id) {
        try {
            for (DataMapping dataMapping : list) {
                Object obj = redisUtils.get(dataMapping.getId());
                String string = dataMapping.getValue();
                if (string != null) {
                    DataMappingVo vo = (DataMappingVo) obj;
                    String object = vo.getName();
                    if (object.equalsIgnoreCase("true")) {
                        object = "1";
                    } else if (object.equalsIgnoreCase("false")) {
                        object = "0";
                    }
                    long recordCate = dataMapping.getRecordCate();
                    // 添加报警内容
                    AlarmInformation alarm = new AlarmInformation();
                    String replace = UUID.randomUUID().toString().replace("-", "");
                    alarm.setId(replace);
                    String equipId = dataMapping.getEquipId();
                    alarm.setEquipId(equipId);
                    Equipment equipment1 = equipmentMapper.selectById(equipId);
                    alarm.setEquipName(equipment1 != null ? equipment1.getEquipNumber() : "");
                    alarm.setMappingId(dataMapping.getId());
                    alarm.setMappingName(dataMapping.getDataName());
                    alarm.setNoticeType("设备告警");
                    alarm.setIsDel(0);// 默认是未删除
                    alarm.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    DataMappingVo dataMappingVo = new DataMappingVo();
                    // 判断是报警还是工作()
                    if (recordCate == AlarmEnum.THREE.getCode() && !object.equals(string)) {
                        DictDetail dictionaries = dictDetailMapper.selectDictDetailLabel(recordCate, string);
                        if (dictionaries != null) {
                            alarm.setNoticeContent(dictionaries.getLabel());
                            alarm.setType(1); // 任务类型记录
                            alarmInformationMapper.insert(alarm);
                        } else {
                            alarm.setNoticeContent("其他");
                            alarm.setType(1);
                            alarmInformationMapper.insert(alarm);
                        }
                    }
                    if (recordCate == AlarmEnum.SIX.getCode() && !object.equals(string)) {
                        DictDetail dictionaries = dictDetailMapper.selectDictDetailLabel(recordCate, string);
                        if (dictionaries != null) {
                            alarm.setNoticeContent(dictionaries.getLabel());
                            alarm.setType(2); // 报警类型记录
                            alarmInformationMapper.insert(alarm);
                        } else if (recordCate != 0) {
                            alarm.setNoticeContent("其他");
                            alarm.setType(2); // 报警类型记录
                            alarmInformationMapper.insert(alarm);
                        }
                    }
                    if (recordCate == AlarmEnum.SEVEN.getCode() && !object.equals(string)) {
                        DictDetail dictionaries = dictDetailMapper.selectDictDetailLabel(recordCate, string);
                        if (dictionaries != null) {
                            alarm.setNoticeContent(dictionaries.getLabel());
                            alarm.setType(0);// 任务报警类型记录
                            alarmInformationMapper.insert(alarm);
                        } else {
                            alarm.setNoticeContent("其他");
                            alarm.setType(0);
                            alarmInformationMapper.insert(alarm);
                        }
                    }
                    if (recordCate == AlarmEnum.EIGHT.getCode() && !object.equals(string)) {
                        DictDetail dictionaries = dictDetailMapper.selectDictDetailLabel(recordCate, string);
                        if (dictionaries != null && string.equals(AlarmEnum.ONE.getCode().toString())) {
                            alarm.setNoticeContent(dictionaries.getLabel());
                            alarm.setType(2); // 报警类型记录
                            alarmInformationMapper.insert(alarm);
                        } else if (!string.equals(AlarmEnum.ONE.getCode().toString()) && !string.equals("0")) {
                            alarm.setNoticeContent("其他");
                            alarm.setMappingName("其他");
                            alarm.setType(2); // 报警类型记录
                            alarmInformationMapper.insert(alarm);
                        }
                    }
                    Date date = new Date();
                    long time = date.getTime();
                    if (recordCate == AlarmEnum.TWENTY_TWO.getCode() && !object.equals(string)) {
                        Equipment equipment = equipmentMapper.selectById(equipId);
                        if (equipment != null) {
                            if (object != null && !object.equals("")) {
                                int sum = Integer.parseInt(object);
                                if (string.equals("")) {
                                    string = "0";
                                }
                                if (!object.equals(string)) {
                                    equipment.setRunningState(Integer.parseInt(string));
                                    equipmentMapper.updateById(equipment);
                                    Long time1 = vo.getTime();
                                    Long hour = (time - time1) / 1000;
                                    equipmentOperationService.addOperation(equipId, sum, hour);
                                }
                            }
                        }
                    }
                    if (!object.equals(string)) {
                        dataMappingVo.setTime(time);
                    } else {
                        dataMappingVo.setTime(vo.getTime());
                    }
                    dataMappingVo.setName(string);
                    redisUtils.del(dataMapping.getId());
                    redisUtils.set(dataMapping.getId(), dataMappingVo);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理报警记录
     *
     * @param alarmInformation
     */
    @Override
    public void updateAlarmInformation(AlarmInformation alarmInformation) {
        for (String id : alarmInformation.getIds()) {
            if (alarmInformation.getExecUserId() != null) {
                throw new BadRequestException("处理人不能为空");
            }
            User user = sysUserMapper.selectById(alarmInformation.getExecUserId());
            if (alarmInformation.getExecContent() != null) {
                throw new BadRequestException("处理内容不能为空");
            }
            AlarmInformation alarm = alarmInformationMapper.selectById(id);
            alarm.setExecTime(new Timestamp(System.currentTimeMillis()));
            alarm.setExecUserId(user.getId());
            alarm.setExecUserName(user.getNickName());
            alarm.setExecContent(alarmInformation.getExecContent());
            alarmInformationMapper.updateById(alarm);
        }
    }

    public void queryDataMapping() {
        QueryWrapper<DataMapping> wrapper = new QueryWrapper<>();
        List<DataMapping> dataMappings = dataMappingMapper.selectList(wrapper);
        for (DataMapping dataMapping : dataMappings) {
            if (dataMapping != null) {
                Object valueOfPoint = getValueOfPoint(dataMapping.getDataAddr(), RedisOPCItem.ITEM_VALUE);
                Date date = new Date();
                long time = date.getTime();
                DataMappingVo dataMappingVo = new DataMappingVo();
                dataMappingVo.setTime(time);
                if (valueOfPoint != null) {
                    String string = valueOfPoint.toString();
                    if (string.equalsIgnoreCase("true")) {
                        string = "1";
                    } else if (string.equalsIgnoreCase("false")) {
                        string = "0";
                    }
                    dataMappingVo.setName(string);
                    redisUtils.set(dataMapping.getId(), dataMappingVo);
                } else {
                    dataMappingVo.setName("5");
                    redisUtils.set(dataMapping.getId(), dataMappingVo);
                }
            }
        }
        cacheService.deleteRunningKeys(equipmentMapper, redisUtils);
        Calendar cal = Calendar.getInstance();
        Date date = new Date(); //现在的日期
        cal.setTime(date);
        int minutes = cal.get(Calendar.MINUTE); // 分
        int seconds = cal.get(Calendar.SECOND); // 秒
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String format1 = format.format(date);
        int hour = cal.get(Calendar.HOUR_OF_DAY); // 时
        EquipmentQueryCriteria equipmentQueryCriteria = new EquipmentQueryCriteria();
        List<Equipment> equipment = equipmentService.queryAll(equipmentQueryCriteria);
        for (Equipment equip : equipment) {

            if (equip.getDeviceType() == auxiliary && equip.getEquipCategoryId() == type) {
                boolean b = redisUtils.hasKey(equip.getId());
                if (!b) {
                    DataMappingVo dataMappingVo = new DataMappingVo();
                    long time = date.getTime();
                    dataMappingVo.setName("5");
                    dataMappingVo.setTime(time);
                    redisUtils.set(equip.getId(), dataMappingVo);
                }
            }
            KanbanStatistics kanbanStatistics = kanbanStatisticsService.queryKanbanStatistics(equip.getId());
            if (kanbanStatistics != null) {
                cacheService.initSingleRunningStat(kanbanStatistics, redisUtils);
                String format2 = format.format(kanbanStatistics.getCreateTime());
                long shutdownTime = kanbanStatistics.getShutdownTime();
                long runningTime = kanbanStatistics.getRunningTime();

                long total = shutdownTime + runningTime;
                long sum = (hour * 3600) + (minutes * 60) + seconds;
                if (!format1.equals(format2)) {
                    KanbanStatistics kanban = new KanbanStatistics();
                    kanban.setShutdownTime(sum);
                    kanban.setShutdownQuantity(1);

                    MonthlyStatistics statistics = monthlyStatisticsService.queryMonthlyStatistics(equip.getId());
                    if (statistics != null) {
                        Integer day = cal.get(Calendar.DAY_OF_MONTH) - 1;
                        long montCount = day * 86400;

                        long monthlyOperationTime = statistics.getMonthlyOperationTime();
                        long monthlyShutdownTime = statistics.getMonthlyShutdownTime();
                        long montTotal = monthlyOperationTime + monthlyShutdownTime + total;

                        if (montCount > montTotal) {
                            long ontSum = montCount - montTotal;
                            statistics.setMonthlyShutdown(statistics.getMonthlyShutdown() + kanbanStatistics.getShutdownQuantity() + 1);
                            statistics.setMonthlyShutdownTime(monthlyShutdownTime + shutdownTime + ontSum);
                        } else {
                            statistics.setMonthlyShutdown(statistics.getMonthlyShutdown() + kanbanStatistics.getShutdownQuantity());
                            statistics.setMonthlyShutdownTime(monthlyShutdownTime + shutdownTime);
                        }

                        statistics.setMonthlyOperation(statistics.getMonthlyOperation() + kanbanStatistics.getRunningQuantity());
                        statistics.setMonthlyOperationTime(monthlyOperationTime + runningTime);
                        monthlyStatisticsService.eatMonthlyStatistics(statistics);
                    } else {
                        MonthlyStatistics monthly = new MonthlyStatistics();
                        // 如果他没有够一天的时间把缺少的补充成关机
                        long number = 86400;

                        if (number > total) {
                            long montCount = number - total;

                            monthly.setMonthlyShutdown(kanbanStatistics.getShutdownQuantity() + 1);
                            monthly.setMonthlyShutdownTime(shutdownTime + montCount);
                        } else {
                            monthly.setMonthlyShutdown(kanbanStatistics.getShutdownQuantity());
                            monthly.setMonthlyShutdownTime(shutdownTime);
                        }
                        monthly.setEquipId(equip.getId());
                        monthly.setMonthlyOperation(kanbanStatistics.getRunningQuantity());
                        monthly.setMonthlyOperationTime(runningTime);
                        monthlyStatisticsService.addMonthlyStatistics(monthly);
                    }

                    kanban.setEquipId(equip.getId());
                    kanban.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    kanbanStatisticsService.del(kanbanStatistics);
                    kanbanStatisticsService.addKanbanStatistics(kanban);
                } else {
                    if (sum > total) {
                        long count = shutdownTime + (sum - total);
                        kanbanStatistics.setShutdownTime(count);
                        kanbanStatistics.setShutdownQuantity(kanbanStatistics.getShutdownQuantity() + 1);
                    }
                    kanbanStatistics.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    kanbanStatisticsService.eatKanbanStatistics(kanbanStatistics);
                }
            } else {
                long sum = (hour * 3600) + (minutes * 60) + seconds;
                KanbanStatistics kanban = new KanbanStatistics();
                kanban.setShutdownQuantity(1);
                kanban.setEquipId(equip.getId());
                kanban.setShutdownTime(sum);
                kanban.setCreateTime(new Timestamp(System.currentTimeMillis()));
                kanbanStatisticsService.addKanbanStatistics(kanban);
            }
            List<MonthlyStatusRecord> monthlyStatusRecords = monthlyStatusRecordService.queryMonthlyStatusRecordTotal(equip.getId(), format1);
            if (monthlyStatusRecords.size() < hour) {
                int size = monthlyStatusRecords.size();
                int sum = hour - size;
                for (int i = 0; i < sum; i++) {
                    MonthlyStatusRecord monthlyStatusRecord = new MonthlyStatusRecord();
                    monthlyStatusRecord.setEquipId(equip.getId());
                    monthlyStatusRecord.setCreationDate(format1);
                    monthlyStatusRecord.setStatus(5);
                    monthlyStatusRecordService.insert(monthlyStatusRecord);
                }
            }
        }
    }

    /**
     * 根据点位 tagName 获取对应的 hash 项
     *
     * @param tagName 标签
     * @param item    哈希项
     */
    public Object getValueOfPoint(String tagName, String item) {
        if (redisUtils.hHasKey(tagName, item)) {
            return redisUtils.hget(tagName, item);
        }
        return null;
    }
}
